//package yyy.ab.common.aspect;
//
//
//import com.alibaba.fastjson.JSON;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import lombok.extern.slf4j.Slf4j;
//import org.aspectj.lang.*;
//import org.aspectj.lang.annotation.*;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
//import org.springframework.web.context.request.RequestContextHolder;
//import org.springframework.web.context.request.ServletRequestAttributes;
//import org.springframework.web.multipart.MultipartFile;
//
//import javax.servlet.http.HttpServletRequest;
//import java.io.IOException;
//import java.io.Serializable;
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.util.*;
//
//@Slf4j
//@Aspect
//@Configuration
//public class LogRecordAspect {
//
//    @Autowired
//    private ObjectMapper objectMapper;
//
//    /**
//     * 定义一个切入点.
//     * 解释下：
//     * ~ 第一个 * 代表任意修饰符及任意返回值.
//     * ~ 第二个 * 任意包名
//     * ~ 第三个 * 代表任意方法.
//     * ~ 第四个 * 定义在controller包或者子包
//     * ~ 第五个 * 任意方法
//     * ~ .. 匹配任意数量的参数.
//     */
//    @Pointcut("execution(* yyy.ab..*.controller..*.*(..))")
//    public void excudeService() {
//    }
//
//    /**
//     * 在切点之前织入
//     *
//     * @param joinPoint
//     * @throws Throwable
//     */
//    @Before("excudeService()")
//    public void doBefore(JoinPoint joinPoint) throws Throwable {
//        // 开始打印请求日志
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        HttpServletRequest request = attributes.getRequest();
//        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//        Method method = signature.getMethod();
//        Object[] args = joinPoint.getArgs();
//        StringBuilder params = new StringBuilder();
//        // 请求的方法参数名称
//        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
//        String[] paramNames = u.getParameterNames(method);
//        if (args != null && paramNames != null) {
//            params = handleParams(params, args, Arrays.asList(paramNames));
//        }
//
//        // 打印请求相关参数
//        log.info("========================================== Start ==========================================");
//        // 打印请求 url
//        log.info("URL            : {}", request.getRequestURL().toString());
//        // 打印 Http method
//        log.info("HTTP Method    : {}", request.getMethod());
//        // 打印调用 controller 的全路径以及执行方法
//        log.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
//        // 打印请求的 IP
//        log.info("IP             : {}", request.getRemoteAddr());
//        // 打印请求入参
//        log.info("Request Args   : {}", params.toString());
//    }
//
//    /**
//     * 在切点之后织入
//     *
//     * @throws Throwable
//     */
//    @After("excudeService()")
//    public void doAfter() throws Throwable {
//        log.info("=========================================== End ===========================================");
//        // 每个请求之间空一行
//        log.info("");
//    }
//
//    /**
//     * 环绕
//     *
//     * @param proceedingJoinPoint
//     * @return
//     * @throws Throwable
//     */
//    @Around("excudeService()")
//    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//        long startTime = System.currentTimeMillis();
//        Object result = proceedingJoinPoint.proceed();
//        // 打印出参
//        log.info("Response Args  : {}");//, new Gson().toJson(result));
//        // 执行耗时
//        log.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
//        return result;
//    }
//
//    @SuppressWarnings({"unchecked", "rawtypes"})
//    private StringBuilder handleParams(StringBuilder params, Object[] args, List paramNames) throws IOException {
//        for (int i = 0; i < args.length; i++) {
//            if (args[i] instanceof Map) {
//                Set set = ((Map) args[i]).keySet();
//                List list = new ArrayList();
//                List paramList = new ArrayList<>();
//                for (Object key : set) {
//                    list.add(((Map) args[i]).get(key));
//                    paramList.add(key);
//                }
//                return handleParams(params, list.toArray(), paramList);
//
//            } else {
//                if (args[i] instanceof Serializable) {
//                    Class<?> aClass = args[i].getClass();
//                    try {
//                        aClass.getDeclaredMethod("toString", new Class[]{null});
//                        // 如果不抛出 NoSuchMethodException 异常则存在 toString 方法 ，安全的 writeValueAsString ，否则 走 Object的 toString方法
//                        params.append("  ").append(paramNames.get(i)).append(": ").append(objectMapper.writeValueAsString(args[i]));
//                    } catch (NoSuchMethodException e) {
//                        params.append("  ").append(paramNames.get(i)).append(": ").append(objectMapper.writeValueAsString(args[i].toString()));
//                    }
//
//                } else if (args[i] instanceof MultipartFile) {
//                    MultipartFile file = (MultipartFile) args[i];
//                    params.append("  ").append(paramNames.get(i)).append(": ").append(file.getName());
//                } else {
//                    params.append("  ").append(paramNames.get(i)).append(": ").append(args[i]);
//                }
//            }
//        }
//        return params;
//    }
//}
